home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / _archvrs / unix / zoo-2_1.lha / zoo-2.1 / needed.c < prev    next >
C/C++ Source or Header  |  1991-10-01  |  8KB  |  235 lines

  1. #ifndef LINT
  2. static char sccsid[]="@(#) needed.c 2.16 88/01/31 15:54:37";
  3. #endif /* LINT */
  4.  
  5. /*
  6. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  7. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  8. */
  9.  
  10. #define    STRCMP(s1,op,s2)        (strcmp(s1,s2) op 0)
  11.  
  12. #include "options.h"
  13. /* Accepts a filename from an archive and returns 1 if a command-line
  14.    argument filename matches it.  Otherwise returns 0. Returns
  15.    1 if no arguments were supplied (so by default, all files will
  16.    be extracted */
  17.  
  18. #include "zoo.h"
  19.  
  20. #ifdef NEEDCTYP
  21. #include <ctype.h>              /* for tolower() */
  22. #else
  23. #include "portable.h"
  24. #endif
  25.  
  26. #include "zooio.h"
  27. #include "zoofns.h"
  28. #include "various.h"
  29. #include "debug.h"
  30.  
  31. extern int next_arg;          /* filenames start at this position */
  32. extern int arg_count;         /* count of arguments supplied to program */
  33. extern char **arg_vector;     /* vector of arguments supplied to program */
  34. /* Uses FIRST_ARG in zoo.h, so must be recompiled when switching
  35.    between Ooz and Zoo */
  36.  
  37. int needed(pathname, direntry, header)
  38. char *pathname;
  39. struct direntry *direntry;
  40. struct zoo_header *header;
  41. {
  42.    register int i;
  43.    register char *arg;
  44.    char *justname;
  45.     char arg_copy[PATHSIZE];                /* working copy of an argument */
  46.     char path_copy[PATHSIZE];                /* working copy of pathname */
  47.     char *p;                                        /* a temporary pointer */
  48.     char *q;                                        /* a temporary pointer */
  49.  
  50.     /* if no filenames supplied, match latest version of each 
  51.         (but match any version if versions not enabled) */
  52.    if (arg_count <= FIRST_ARG &&
  53.             (!(header->vdata & VFL_ON) || 
  54.             !(direntry->vflag & VFL_ON) || (direntry->vflag & VFL_LAST))) {
  55.          
  56.       return (1);                       /* .. then all files are needed */
  57.     }
  58.  
  59.    /* count backwards and stop if '+' is encountered */
  60.    for (i = arg_count-1;  i >= next_arg; i--) {
  61.       arg = arg_vector[i];
  62. #ifdef FOLD
  63.       str_lwr(pathname); str_lwr(arg);
  64. #endif
  65. #ifdef DEBUG
  66. printf("needed: testing [%s] and [%s]\n", pathname, arg);
  67. #endif
  68.       if (STRCMP(arg,==,"+"))
  69.          return (0);
  70.  
  71.       /* If the argument contains a slash, the match fails if the
  72.          path prefixes don't match */
  73.       if (strchr(arg, *(char *)PATH_CH) != NULL) {      /* found slash */
  74.          strcpy(arg_copy,arg);
  75.          strcpy(path_copy,pathname);
  76.          p = findlast(arg_copy, PATH_CH);
  77.          if (p != NULL)
  78.             *p = '\0';
  79.             else {
  80.                 p = findlast (arg_copy, VER_INPUT);
  81.                 if (p != NULL)
  82.                     *p = '\0';
  83.             }
  84.          p = findlast(path_copy, PATH_CH);
  85.          if (p != NULL)
  86.             *p = '\0';
  87.             else {
  88.                 p = findlast (path_copy, VER_DISPLAY);
  89.                 if (p != NULL)
  90.                     *p = '\0';
  91.             }
  92.          if (!match_half(path_copy, arg_copy)) {
  93. #ifdef DEBUG
  94. printf ("needed(): match failed for [%s] and [%s]\n",
  95.     path_copy, arg_copy);
  96. #endif
  97.             continue;                     /* no match this time in loop */
  98.          }
  99.       }
  100.  
  101.       /*
  102.       We reach here either if the pattern had no slashes, or if it had a 
  103.         slash but the path prefixes matched.  Now we will test to see if the 
  104.         filename parts match.  If the argument contains VER_INPUT character, 
  105.         then this separates the filename from a version number, and only that 
  106.         specific version will match.  If not, then only the latest version 
  107.         will match.  However, if the argument has a version character but
  108.         nothing following it, that matches all versions.  Also, version
  109.         0 matches only the latest version and version ^0 matches all
  110.         versions except the latest one.
  111.       */
  112.         strcpy (arg_copy, arg);                            /* local copy of argument */
  113.         strcpy (path_copy, pathname);                    /* local copy of pathname */
  114.         p = findlast(arg_copy, VER_INPUT);            /* p is version in argument */
  115.         q = findlast(path_copy, VER_DISPLAY);        /* q is version in archive */
  116.         if (p != NULL && p != lastptr(arg_copy)) {/* nonnull version in arg */
  117.             if (q != NULL) {                                /* nonnull ver. in archive */
  118.                 char *pp = p+1;                            /* point to actual version */
  119.                 char *qq = q+1;
  120.                 if (STRCMP(pp, ==, "0") && !(direntry->vflag & VFL_LAST) ||
  121.                      STRCMP(pp, ==, "^0") && (direntry->vflag & VFL_LAST)) {
  122.                         debug(("needed:  no match versions [%s] and [%s]\n", qq, pp))
  123.                         continue;
  124.                 }
  125.                 if (STRCMP(pp, !=, "0") && STRCMP(pp, !=, "^0") &&
  126.                     !match_half (qq, pp)) {
  127.                     debug(("needed:  no match versions [%s] and [%s]\n", qq, pp))
  128.                     continue;                                    /* no match this loop */
  129.                 }
  130.             }
  131.         }
  132.         /* Special case test:  If argument has version but no filename,
  133.             then filename is assumed to match */
  134.         if (p == arg_copy) {                                /* 1st char is version char */
  135.             return (1);                                        /* .. so declare a match */
  136.         }
  137.  
  138.         /* 
  139.         Reach here if argument has no version character, or if argument has 
  140.         version character and it matches version in pathname.  Now we check to 
  141.         see if argument has no version character and if pathname is latest 
  142.         version.  If so, the versions do match;  if not, then the match fails.  
  143.         But if version numbering is not enabled, then versions always match.
  144.         If the match fails, we do a "continue", else we fall through and
  145.         proceed to test the filenames.  (Note:  It is intuitively better
  146.         to first compare filenames and then see if versions match, but
  147.         since they are both just independent fields, it's equally correct
  148.         to compare versions first, as we are doing here, and then see if
  149.         filenames match.  It may even be more efficient.)
  150.         */
  151.  
  152.         if (p == NULL &&                                         /* no version char typed */
  153.                 !(                                                    /* NOT */
  154.                     (direntry->vflag & VFL_ON) == 0 ||     /*  no versions */
  155.                     (direntry->vflag & VFL_LAST) ||        /*  .. or latest version */
  156.                     q == NULL                                    /*  .. or no version char */
  157.                 )
  158.             )
  159.         {
  160. #ifdef DEBUG
  161. printf("needed: fail--no version typed and not latest version\n");
  162. #endif
  163.             continue;                                            /* match fails */
  164.         } 
  165.         /* versions match and we fall through */;
  166.  
  167.         /* reach here if versions match -- so strip them and compare rest */
  168.         if (p != NULL)
  169.             *p = '\0';                            /* strips version from arg_copy */
  170.         if (q != NULL)
  171.             *q = '\0';                            /* strips version from path_copy */
  172.  
  173.         justname = nameptr(path_copy);        /* filename without any pathname */
  174.       if (match_half (justname, nameptr(arg_copy)))
  175.          return (1);
  176. #ifdef DEBUG
  177. printf ("needed: fname-only match failed [%s] and [%s]\n",
  178.  justname, nameptr(arg_copy));
  179. #endif
  180.  
  181.       /* try for a character range */
  182.       if (match_half (arg, "?-?")) {             /* character range given */
  183.          if (arg[0] <= *justname && arg[2] >= *justname)
  184.             return (1);
  185.       }
  186.    }
  187.    return (0);
  188.  
  189. } /* needed */
  190.  
  191. /***********************/
  192. /*
  193. match_half() compares a pattern with a string.  Wildcards accepted in
  194. the pattern are:  "*" for zero or more arbitrary characters;  "?"
  195. for any one characters.  Unlike the MS-DOS wildcard match, "*" is
  196. correctly handled even if it isn't at the end of the pattern. ".'
  197. is not special.
  198.  
  199. Originally written by Jeff Damens of Columbia University Center for
  200. Computing Activities.  Taken from the source code for C-Kermit version
  201. 4C.
  202. */
  203.  
  204. int match_half (string, pattern) 
  205. register char *string, *pattern;
  206. {
  207.    char *psave,*ssave;        /* back up pointers for failure */
  208.    psave = ssave = NULL;
  209.    while (1) {
  210. #ifdef IGNORECASE
  211.       for (; 
  212.          tolower(*pattern) == tolower(*string); 
  213.          pattern++,string++                        )  /* skip first */
  214. #else
  215.       for (; *pattern == *string; pattern++,string++)  /* skip first */
  216. #endif /* IGNORECASE */
  217.  
  218.          if (*string == '\0') 
  219.             return(1);                          /* end of strings, succeed */
  220.       if (*string != '\0' && *pattern == '?') {
  221.          pattern++;                             /* '?', let it match */
  222.          string++;
  223.       } else if (*pattern == '*') {             /* '*' ... */
  224.          psave = ++pattern;                     /* remember where we saw it */
  225.          ssave = string;                        /* let it match 0 chars */
  226.       } else if (ssave != NULL && *ssave != '\0') {   /* if not at end  */
  227.          /* ...have seen a star */
  228.          string = ++ssave;                      /* skip 1 char from string */
  229.          pattern = psave;                       /* and back up pattern */
  230.       } else 
  231.          return(0);                             /* otherwise just fail */
  232.    }
  233. }
  234.  
  235.